#include "initialize.h"
static void SysclockInit(void);
static void SysclkDebugInit(void);
static void GpioInit(void);
void Initialize(void)
{
	SysclockInit();
	#if(Sysclk_DebugMode==1)
	SysclkDebugInit();
	#endif
	GpioInit();
}

/*OSC Freq:12MHZ SYSCLK Freq:64MHZ*/
static void SysclockInit(void)
{
	/* Enable HSEON bit in the Clock control 
    register (RCC_CR).*/ 
	RCC->CR |= (1<<16);
	/*The HSERDY flag in the Clock control register (RCC_CR) indicates if the HSE oscillator is 
    stable or not.*/
	uint32_t RCCtemp;
	do
	{
	 RCCtemp = RCC->CR;		
	}while( (RCCtemp & (1<<17)) == 0);
	/*config the number of wait states (LATENCY) in the FLASH access control register (FLASH_ACR)*/
	FLASH->ACR |= (1<<1);
	/*enable CPU Prefetch*/
	FLASH->ACR |= (1<<8);
	/*disable PLL*/
	RCC->CR &=~ (1<<24);
	/*Wait until PLLRDY is cleared. The PLL is now fully stopped.*/
	while( ((RCC->CR) & (1<<25)) !=0)
				;
	/*config input resource of pll as HSE*/
	RCC->PLLCFGR |= (1<<0)+(1<<1);
	/*fVCO = fPLLIN × (N / M)
      fPLLP = fVCO / P
      fPLLQ = fVCO / Q
      fPLLR = fVCO / R
	fPLLIN=12MHZ */
	/*Set division factor M=2*/
	RCC->PLLCFGR &=~ (7<<4);
	RCC->PLLCFGR |= (1<<4);
	/*Set division factor N=32*/
	RCC->PLLCFGR &=~ (127<<8);
	RCC->PLLCFGR |= (32<<8);
	/*Set division factor R=3*/
	RCC->PLLCFGR &=~ (7<<29);
	RCC->PLLCFGR |= (1<<30);
	/*Enable PLLRCLK output*/		   
	RCC->PLLCFGR |= (1<<28);
	/*enable PLL*/
	RCC->CR |= (1<<24);
	/*Wait until PLLRDY is set. The PLL is now fully ready.*/
	while( ((RCC->CR) & (1<<25)) ==0)
				;	
	/*choose PLLRCLK as SYSCLK source*/
	RCC->CFGR &=~ (7<<0);
	RCC->CFGR |= (2<<0);
	/*wait for PLLRCLK be the SYSCLK source*/
	while( ((RCC->CFGR)&(7<<3)) != (2<<3)  )
					;
}

static void SysclkDebugInit(void)
{
	/*config Microcontroller clock output clock selector*/
	RCC->CFGR &=~ (15<<24);
	RCC->CFGR |= (1<<24);
	/*config Microcontroller clock output prescaler*/
	RCC->CFGR &=~ (15<<28);
	RCC->CFGR |= (0<<28);
	/*enable clock of gpioA*/
	RCC->IOPENR &=~ (1<<0);
	RCC->IOPENR |= (1<<0);
	/*config gpio mode*/
	GPIOA->MODER |= (2<<16);
	/*config gpio speed*/
	GPIOA->OSPEEDR |= (3<<16);
	/*config gpio AF*/
	GPIOA->AFR[1] |= (0<<0);
}

/*PB4(O) LED3
  PC6(O) LED2
  PC7(O) LED1
  PC14(O) DR
  PC15(I) KEY
  PD0(O)  RES1
  PD1(O)  DC1
  PD2(O)  BLK
  PD3(O)  TP1
*/

static void GpioInit(void)
{
	/*Initialize gpio B*/
	/*Set I/O port clock*/
	RCC->IOPENR |= (1<<1);
	/*Set GPIO port mode*/
	GPIOB->MODER &=~ (3<<8);
	GPIOB->MODER |= (1<<8);	
	/*Set GPIO port output speed*/
	GPIOB->OSPEEDR |= (3<<8);
	/*Set GPIO port output data*/
	GPIOB->ODR &=~ (1<<4);
	GPIOB->ODR |= (1<<4);
	
	/*Initialize gpio C*/
	/*Set I/O port clock*/
	RCC->IOPENR |= (1<<2);
	/*Set GPIO port mode*/
	GPIOC->MODER &=~ ((3<<12)+(3<<14)+(3<<28)+(3<<30));
	GPIOC->MODER |= ((1<<12)+(1<<14)+(1<<28)+(0<<30));	
	/*Set GPIO port output speed*/
	GPIOC->OSPEEDR |= ((3<<12)+(3<<14)+(3<<28));
	/*Set GPIO port output data*/
	GPIOC->ODR &=~ ((1<<6)+(1<<7)+(1<<14));
	GPIOC->ODR |= ((1<<6)+(1<<7)+(1<<14));	

	/*Initialize gpio D*/
	/*Set I/O port clock*/
	RCC->IOPENR |= (1<<3);
	/*Set GPIO port mode*/
	GPIOD->MODER &=~ ((3<<0)+(3<<2)+(3<<4)+(3<<6));
	GPIOD->MODER |= ((1<<0)+(1<<2)+(1<<4)+(1<<6));	
	/*Set GPIO port output speed*/
	GPIOD->OSPEEDR |= ((3<<0)+(3<<2)+(3<<4)+(3<<6));
	/*Set GPIO port output data*/
	GPIOD->ODR &=~ ((1<<0)+(1<<2)+(1<<4)+(1<<6));
	GPIOD->ODR |= ((1<<0)+(1<<2)+(1<<4)+(1<<6));	
}